/*!
 * \file te_comm.h
 *
 * \brief TongEASY模块共通文件
 *
 * All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.
 *
 * \version 1.0
 * \author songbb
 * \date 2016/09/24
 *
 */

#ifndef __TE_COMM_H_
#define __TE_COMM_H_

#include <sys/time.h>

#include "frlog.h"
#include "frreport_comm.h"

#include "te_core.h"

#define APM_TE_DBG 0              //!< TE的Debug开关
#define APM_TE_ENABLE_FRLOG 0     //!< FRLOG开关

#define APM_TE_FLAG_UNSET -1      //!< 标识符变量的初始化值

#define APM_TE_HASH_SIZE 100      //!< TongEASY模块哈希桶的最大尺寸

#define APM_TE_DETECT_MAX 3

#define APM_TE_HDR_LEN 185        //!< 包头长度 - 到全局事务超时时间为止
#define APM_TE_CVS_HDR_LEN 205    //!< 包头长度 - 会话模式，全局事务超时时间字段后面还包含5个未知的字段

#define TE_PKT_TYPE2STR(x) ((x==TE_PKT_TYPE_UNKNOWN)?"UNKNOWN": \
                               ((x==TE_PKT_TYPE_SYNC_ASYNC_REQ)?"5Z0200": \
                               ((x==TE_PKT_TYPE_SYNC_ASYNC_RESP)?"5Z0210": \
                               ((x==TE_PKT_TYPE_SYNC_ASYNC_COMMIT_REQ)?"5Z0202": \
                               ((x==TE_PKT_TYPE_SYNC_ASYNC_COMMIT_RESP)?"5Z0212": \
                               ((x==TE_PKT_TYPE_SYNC_ASYNC_ABORT_REQ)?"5Z0402": \
                               ((x==TE_PKT_TYPE_SYNC_ASYNC_ABORT_RESP)?"5Z0412": \
                               ((x==TE_PKT_TYPE_CVS_REQ)?"5C0200": \
                               ((x==TE_PKT_TYPE_CVS_RESP)?"5C0202": \
                               ((x==TE_PKT_TYPE_CVS_CONN_REQ)?"5C0800": \
                               ((x==TE_PKT_TYPE_CVS_CONN_RESP)?"5C0810": \
                               ((x==TE_PKT_TYPE_CVS_DISCONN)?"5C0402":"UNKNOWN"))))))))))))  //!< 数据包类型转字符串

#define TE_PKT_TYPE2CNSTR(x) ((x==TE_PKT_TYPE_UNKNOWN)?"UNKNOWN": \
                               ((x==TE_PKT_TYPE_SYNC_ASYNC_REQ)?"用户同步/异步请求包": \
                               ((x==TE_PKT_TYPE_SYNC_ASYNC_RESP)?"用户同步/异步应答包": \
                               ((x==TE_PKT_TYPE_SYNC_ASYNC_COMMIT_REQ)?"用户同步/异步提交包": \
                               ((x==TE_PKT_TYPE_SYNC_ASYNC_COMMIT_RESP)?"用户同步/异步提交应答包": \
                               ((x==TE_PKT_TYPE_SYNC_ASYNC_ABORT_REQ)?"用户同步/异步回滚包": \
                               ((x==TE_PKT_TYPE_SYNC_ASYNC_ABORT_RESP)?"用户同步/异步回滚应答包": \
                               ((x==TE_PKT_TYPE_CVS_REQ)?"用户会话交易传输请求包": \
                               ((x==TE_PKT_TYPE_CVS_RESP)?"用户会话交易传输响应包": \
                               ((x==TE_PKT_TYPE_CVS_CONN_REQ)?"用户会话交易建立连接请求包": \
                               ((x==TE_PKT_TYPE_CVS_CONN_RESP)?"用户会话交易建立连接应答包": \
                               ((x==TE_PKT_TYPE_CVS_DISCONN)?"用户会话交易拆除连接通知包":"UNKNOWN"))))))))))))  //!< 数据包类型转中文字符串

#define APM_DTS_REPORT_MODULE_NAME "dts"        //!< DTS数据上报模块名
#define APM_DTS_REPORT_REQ_SERVICE_NAME APM_REPORT_KEY_REQ"."APM_DTS_REPORT_MODULE_NAME".service.name"      //!< 服务名或者程序名，例如to_upper
#define APM_DTS_REPORT_REQ_SERVICE_METHOD APM_REPORT_KEY_REQ"."APM_DTS_REPORT_MODULE_NAME".service.method"  //!< call
#define APM_DTS_REPORT_REQ_ARG_SIZE APM_REPORT_KEY_REQ"."APM_DTS_REPORT_MODULE_NAME".service.arg.size"      //!< 请求参数的个数
#define APM_DTS_REPORT_REQ_ARG_DATA APM_REPORT_KEY_REQ"."APM_DTS_REPORT_MODULE_NAME".service.arg.1"         //!< 请求参数
#define APM_DTS_REPORT_RESP_ARG_SIZE APM_REPORT_KEY_RESP"."APM_DTS_REPORT_MODULE_NAME".service.return.size" //!< 响应参数的个数
#define APM_DTS_REPORT_RESP_ARG_DATA APM_REPORT_KEY_RESP"."APM_DTS_REPORT_MODULE_NAME".service.return.1"    //!< 响应参数

#define APM_TE_REPORT_TID APM_REPORT_KEY_REQ"."APM_DTS_REPORT_MODULE_NAME".tid"                          //!< 事务序号
#define APM_TE_REPORT_SUBTID APM_REPORT_KEY_REQ"."APM_DTS_REPORT_MODULE_NAME".subtid"                    //!< 事务分支序号

#define APM_TE_REPORT_REQ_PACKET_TYPE APM_REPORT_KEY_REQ"."APM_DTS_REPORT_MODULE_NAME".packet_type"      //!< 数据包类型
#define APM_TE_REPORT_REQ_ORIGINAL_NODE APM_REPORT_KEY_REQ"."APM_DTS_REPORT_MODULE_NAME".original_node"  //!< 发起节点名
#define APM_TE_REPORT_REQ_SEND_NODE APM_REPORT_KEY_REQ"."APM_DTS_REPORT_MODULE_NAME".send_node"          //!< 发送节点名
#define APM_TE_REPORT_REQ_RECV_NODE APM_REPORT_KEY_REQ"."APM_DTS_REPORT_MODULE_NAME".receive_node"       //!< 接收节点名
#define APM_TE_REPORT_REQ_KEY_DATA APM_REPORT_KEY_REQ"."APM_DTS_REPORT_MODULE_NAME".key_data"            //!< 关键数据
#define APM_TE_REPORT_REQ_FILENAME APM_REPORT_KEY_REQ"."APM_DTS_REPORT_MODULE_NAME".filename"            //!< 文件名

#define APM_TE_REPORT_RESP_PACKET_TYPE APM_REPORT_KEY_RESP"."APM_DTS_REPORT_MODULE_NAME".packet_type"    //!< 数据包类型
#define APM_TE_REPORT_RESP_ORIGINAL_NODE APM_REPORT_KEY_RESP"."APM_DTS_REPORT_MODULE_NAME".original_node" //!< 发起节点名
#define APM_TE_REPORT_RESP_SEND_NODE APM_REPORT_KEY_RESP"."APM_DTS_REPORT_MODULE_NAME".send_node"        //!< 发送节点名
#define APM_TE_REPORT_RESP_RECV_NODE APM_REPORT_KEY_RESP"."APM_DTS_REPORT_MODULE_NAME".receive_node"     //!< 接收节点名
#define APM_TE_REPORT_RESP_KEY_DATA APM_REPORT_KEY_RESP"."APM_DTS_REPORT_MODULE_NAME".key_data"          //!< 关键数据
#define APM_TE_REPORT_RESP_FILENAME APM_REPORT_KEY_RESP"."APM_DTS_REPORT_MODULE_NAME".filename"          //!< 文件名

#define KRED        "\x1B[0;31m"    //!< ANSI红色
#define KSALMON     "\x1B[1;31m"    //!< ANSI鲑红色
#define KGREEN      "\x1B[0;32m"    //!< ANSI绿色
#define KLIMEGREEN  "\x1B[1;32m"    //!< ANSI青柠色
#define KYELLOW     "\x1B[0;33m"    //!< ANSI黄色
#define KORANGE     "\x1B[0;34m"    //!< ANSI橘黄色
#define KBLUE       "\x1B[1;34m"    //!< ANSI蓝色
#define KMAGENTA    "\x1B[0;35m"    //!< ANSI洋红色
#define KPINK       "\x1B[1;35m"    //!< ANSI粉色
#define KCYAN       "\x1B[0;36m"    //!< ANSI青色
#define RESET       "\x1B[0m"       //!< ANSI颜色重置

#if APM_TE_DBG
    #define TE_PRINT(...) printf(__VA_ARGS__)                         //!< 普通的打印
    #define TE_PRINT_DETAIL(...) (printf("[%s, Line:%u, %s()]",\
                        __FILE__,__LINE__,__func__),\
                        printf(__VA_ARGS__))                            //!< 打印Detail
    #define TE_PRINT_DBG(...) (printf("[%s, Line:%u, %s()]",\
                        __FILE__,__LINE__,__func__),\
                        printf(KGREEN),\
                        printf(" "__VA_ARGS__),\
                        printf(RESET))                                  //!< 打印debug
    #define TE_PRINT_FATAL(...) (printf("[%s, Line:%u, %s()]",\
                        __FILE__,__LINE__,__func__),\
                        printf(KORANGE),\
                        printf(" "__VA_ARGS__),\
                        printf(RESET))                                  //!< 打印fatal
    #define TE_PRINT_EMERG(...) (printf("[%s, Line:%u, %s()]",\
                        __FILE__,__LINE__,__func__),\
                        printf(KRED),\
                        printf(" "__VA_ARGS__),\
                        printf(RESET))                                  //!< 打印emergent
    #define TE_PRINT_ALERT(...) (printf("[%s, Line:%u, %s()]",\
                        __FILE__,__LINE__,__func__),\
                        printf(KSALMON),\
                        printf(" "__VA_ARGS__),\
                        printf(RESET))                                  //!< 打印alert
    #define TE_PRINT_CRIT(...) (printf("[%s, Line:%u, %s()]",\
                            __FILE__,__LINE__,__func__),\
                            printf(KMAGENTA),\
                            printf(" "__VA_ARGS__),\
                            printf(RESET))                              //!< 打印critical
    #define TE_PRINT_ERR(...) (printf("[%s, Line:%u, %s()]",\
                        __FILE__,__LINE__,__func__),\
                        printf(KPINK),\
                        printf(" "__VA_ARGS__),\
                        printf(RESET))                                  //!< 打印error
    #define TE_PRINT_WARN(...) (printf("[%s, Line:%u, %s()]",\
                        __FILE__,__LINE__,__func__),\
                        printf(KYELLOW),\
                        printf(" "__VA_ARGS__),\
                        printf(RESET))                                  //!< 打印warning
    #define TE_PRINT_NOTICE(...) (printf("[%s, Line:%u, %s()]",\
                        __FILE__,__LINE__,__func__),\
                        printf(KLIMEGREEN),\
                        printf(" "__VA_ARGS__),\
                        printf(RESET))                                  //!< 打印notice
    #define TE_PRINT_INFO(...) (printf("[%s, Line:%u, %s()]",\
                            __FILE__,__LINE__,__func__),\
                            printf(KBLUE),\
                            printf(" "__VA_ARGS__),\
                            printf(RESET))                              //!< 打印info
    #define PRINT_HEX_STRING(a,b,c) (printf("[%s, Line:%u, %s()] ",\
                            __FILE__,__LINE__,__func__),\
                            printf(KCYAN),\
                            printf(a":["),te_print_hex_string(b,c),printf("]\n"),\
                            printf(RESET))                              //!< 打印十六进制字符串
    #define TE_PRINT_PACKET_SPECIFIED(tag, packet, offset, len) (printf("[%s, Line:%u, %s()] ",\
                            __FILE__,__LINE__,__func__),\
                            printf(KORANGE),\
                            printf(tag":["),te_print_packet_specified(packet,offset,len),printf("]\n"),\
                            printf(RESET))                              //!< 以十六进制形式打印数据包的指定位置开始的数据
    #define TE_PRINT_PACKET_CURRENT(a,b) (printf("[%s, Line:%u, %s()] ",\
                            __FILE__,__LINE__,__func__),\
                            printf(KCYAN),\
                            printf(a":["),te_print_packet_current(b),printf("]\n"),\
                            printf(RESET))                              //!< 以十六进制打印数据包当前位置开始的数据
    #define TE_PRINT_PACKET(a,b) (printf("[%s, Line:%u, %s()] ",\
                            __FILE__,__LINE__,__func__),\
                            printf(KCYAN),\
                            printf(a":["),te_print_packet(b),printf("]\n"),\
                            printf(RESET))                              //!< 以十六禁止打印整个数据包
    #define TE_PRINT_TIMEVAL(a,b) (printf("[%s, Line:%u, %s()]",\
                            __FILE__,__LINE__,__func__),\
                            printf(KGREEN),\
                            printf(" %s", a), \
                             te_print_timeval(b),\
                             printf(RESET))                             //!< 打印timeval
#else
    #define TE_PRINT(...)
    #define TE_PRINT_DETAIL(...)
    #define TE_PRINT_DBG(...)
    #define TE_PRINT_FATAL(...)
    #define TE_PRINT_EMERG(...)
    #define TE_PRINT_ALERT(...)
    #define TE_PRINT_CRIT(...)
    #define TE_PRINT_ERR(...)
    #define TE_PRINT_WARN(...)
    #define TE_PRINT_NOTICE(...)
    #define TE_PRINT_INFO(...)
    #define PRINT_HEX_STRING(a,b,c)
    #define TE_PRINT_PACKET_SPECIFIED(tag, packet, offset, len)
    #define TE_PRINT_PACKET_CURRENT(a,b)
    #define TE_PRINT_PACKET(a,b)
    #define TE_PRINT_TIMEVAL(a,b)
#endif

#if APM_TE_ENABLE_FRLOG
    #define TE_FRLOG_ERROR(...) FRLOG_ERROR_DETAIL(...)               //!< 打印Log日志
#else
#define TE_FRLOG_ERROR(...)
#endif

#define TE_MALLOCK_ERR TE_PRINT_EMERG("can not malloc memory\n"); \
                          FRLOG_ERROR_DETAIL("can not malloc memory");  //!< malloc执行出错记录

/*!
 * 释放内存
 *
 * \param pp_buffer  (内存两重指针)
 *
 */
void te_free(void **pp_buffer);

/*!
 * 打印时间戳
 *
 * \param st_timestamp  (时间戳)
 *
 */
void te_print_timeval(struct timeval st_timestamp);

/*!
 * 格式化成十六进制字符串
 *
 * \param p_inbuff          (输入的buff)
 * \param i_inbuff_len      (输入的buff长度)
 * \param p_outbuff         (输出的buff)
 * \param i_outbuff_len     (输出的buff长度)
 *
 */
void te_bin_to_hex_string(char *p_inbuff
                        , int i_inbuff_len
                        , char *p_outbuff
                        , int i_outbuff_len);

int te_hex_string_to_bin(const char *p_hex_string
                        , char **pp_out_buff
                        , int *p_out_buff_size);

/*!
 * 按一个字节打印十六进行字符串
 *
 * \param p_buff    (输入的字符串)
 * \param i_len     (输入的字符串长度)
 *
 */
void te_print_hex_string(char *p_buff
                        , int i_len);

/*!
 * 打印指定位置的包内容
 *
 * \param p_st_te_packet      (TongEASY数据包)
 * \param i_pos                 (开始位置)
 * \param i_len                 (长度)
 *
 */
void te_print_packet_specified(L7_te_packet *p_st_te_packet
                                , int i_pos
                                , int i_len);

/*!
 * 打印当前位置开始的包内容
 *
 * \param p_st_te_packet      (TongEASY数据包)
 *
 */
void te_print_packet_current(L7_te_packet *p_st_te_packet);

/*!
 * 打印整个包内容
 *
 * \param p_st_te_packet      (TongEASY数据包)
 *
 */
void te_print_packet(L7_te_packet *p_st_te_packet);

/*!
 * 判断是否处于分片包状态
 *
 * \param p_st_te_packet      (TongEASY数据包)
 *
 * \return 0  失败\n
 *         1  成功
 *
 */
int te_packet_is_in_fragment(L7_te_packet *p_st_te_packet);

void te_free_stmt(L7_te_stmt **pp_st_stmt);

void te_stmt_node_free(Frlist_node *p_st_node);


/*!
 * 上报请求信息
 *
 * \param p_st_conn         (ct信息)
 * \param p_st_te_packet    (TongEASY数据包)
 * \param p_st_body         (数据上报体内容)
 * \param p_st_hash_report  (数据上报用)
 *
 * \return 0  失败\n
 *         1  成功
 *
 */
int te_report_msg_data_req(Conntrack *p_st_conn
                        , L7_te_packet *p_st_te_packet
                        , Frreport_body_data *p_st_body
                        , Frhash_header *p_st_hash_report);

/*!
 * 上报响应信息
 *
 * \param p_st_conn         (ct信息)
 * \param p_st_te_packet    (TongEASY数据包)
 * \param p_st_body         (数据上报体内容)
 * \param p_st_hash_report  (数据上报用)
 *
 * \return 0  失败\n
 *         1  成功
 *
 */
int te_report_msg_data_resp(Conntrack *p_st_conn
                            , L7_te_packet *p_st_te_packet
                            , L7_te_stmt *p_te_stmt
                            , Frreport_body_data *p_st_body
                            , Frhash_header *p_st_hash_report);

#endif
